﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace VirtualCOM
{
    /// <summary>
    /// TCP通信管理类
    /// </summary>
    public class TcpManager
    {
        #region 成员变量

        private TcpClient tcpClient;
        private NetworkStream stream;

        #endregion

        #region Propertys

        /// <summary>
        /// 服务端IP地址
        /// </summary>
        public string IP { get; set; }

        /// <summary>
        /// 服务端端口号
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        /// 接收消息回调
        /// </summary>
        public event Action<byte[]> DataReceived = (bytes) => { };

        #endregion

        #region Methods

        public void Connect()
        {
            tcpClient = new TcpClient();
            tcpClient.Connect(IP, Port);
            stream = tcpClient.GetStream();
            var task = new Task(ReadBytes);
            task.Start();
        }

        public void Send(byte[] bytes)
        {
            if (tcpClient == null || stream == null)
                return;
            if (!tcpClient.Connected)
                return;
            stream.Write(Const.SendHeader, 0, Const.SendHeader.Length);
            stream.Write(bytes, 0, bytes.Length);
            stream.WriteByte(Const.SendEndByte);
        }

        public void Close()
        {
            if (stream != null)
            {
                stream.Flush();
                stream.Close();
            }
            if (tcpClient.Connected)
                tcpClient.Close();
            stream = null;
            tcpClient = null;
        }

        private void ReadBytes()
        {
            if (tcpClient == null || stream == null)
                return;
            if (!tcpClient.Connected)
                return;
            int data = 0;
            bool hasHeader = false;
            List<byte> bytesList = new List<byte>();
            while (true)
            {
                try
                {
                    data = (byte)stream.ReadByte();
                }
                catch (Exception ex)
                {
                    data = -1;
                    System.Diagnostics.Trace.TraceError(ex.ToString());
                }
                if (data == -1)
                    break;
                if (bytesList.Count < Const.ReceiveHeader.Length && !hasHeader)
                {
                    if (data != Const.ReceiveHeader[bytesList.Count])
                        bytesList.Clear();
                    if (data == Const.ReceiveHeader[bytesList.Count])
                        bytesList.Add((byte)data);
                }
                else
                {
                    if (!hasHeader && bytesList.Count == Const.ReceiveHeader.Length)
                    {
                        hasHeader = true;
                        bytesList.Clear();
                    }
                    //确认已经接收到过帧头 之后的所有数据都是消息内容
                    if (hasHeader)
                    {
                        if (data == Const.ReceiveEndByte)
                        {
                            hasHeader = false;
                            this.DataReceived(bytesList.ToArray());
                            bytesList.Clear();
                        }
                        else
                            bytesList.Add((byte)data);
                    }
                }
            }
        }

        #endregion
    }
}
